#ifndef XSTATE_HPP
#define XSTATE_HPP
#include"xsignal/signal.hpp"

class xAbstractState:public SIG::sigReciver{
public:
    virtual ~xAbstractState(){}
    virtual void doAction() = 0;
};

//抽象状态
class xstateMachine;
class xstate:public xAbstractState{
public:
    virtual void doAction(){}

    void setmachine(xstateMachine* m){
        m_machine = m;
    }

    xstateMachine* getmachine(){
        return m_machine;
    }

    template<class sendertype,class  signaltype>
    void addTransition(sendertype *sender,signaltype signalObj,xstate* nextstate);
private:
    xstateMachine* m_machine = nullptr;
public:
    XSIGNAL(sig_entered);
    XSIGNAL(sig_exited);
};

//状态机
class xstateMachine:public xAbstractState{
public:
    friend xstate;
    xstateMachine(){
        m_thrd = std::thread(&xstateMachine::machineAsyncThrd,this); 
    }
    ~xstateMachine(){
        terminate();
        if(m_thrd.joinable())
            m_thrd.join();
    }
public:
    unsigned int thrdid() const{
        std::thread::id tid = m_thrd.get_id();
        return *(unsigned int*)&tid;;
    }
    void start(){
        m_startMachine = true;
    } 

    void terminate(){
        m_terminate = true;
        m_runflag = false;
    } 

    void addstate(xstate*s){
        m_states.push_back(s);
        s->setmachine(this);
    }

    xstate* getCurState() const{
        return m_curState;
    }

    void setInitialState(xstate*s){
        m_curState = s;
    }
private:
    void setstate(xstate *s)
    {
        m_curState = s;
    }
public:
    virtual void doAction(){
        m_curState->doAction();
    }

    void machineAsyncThrd(){
	//
	//[1--创建线程消息队列]
	SIG_THREAD_INIT();

	while (m_startMachine == false && m_terminate== false)
	{
		std::this_thread::sleep_for(std::chrono::seconds(2));
	}
	
	//
	//[2--消息循环]
    if(m_startMachine == true){
        SIG_THREAD_EXEC(m_runflag);
    }
	
	//
	//[3--销毁线程消息队列]
	SIG_THREAD_CLEAR();
    
    //发射状态机完成信号
    xemit(sig_finished)(); 
}
private:
    xstate* m_curState = nullptr;
    std::vector<xstate*> m_states;
    bool m_startMachine = false;
    bool m_runflag = true;
    bool m_terminate = false;
    std::thread m_thrd;
public:
    XSIGNAL(sig_finished);
};

template <class sendertype, class signaltype>
void xstate::addTransition(sendertype *sender, signaltype signalObj, xstate *nextstate)
{
    auto f = [this, nextstate]()
    {
        if (m_machine->getCurState() == this)
        {
            m_machine->setstate(nextstate);
            xemit(nextstate->sig_entered)();
            m_machine->doAction();
            xemit(nextstate->sig_exited)();
        }
    };
    unsigned int thrdid = this->m_machine->thrdid();
    this->recordSignal((sender->*signalObj));
    (sender->*signalObj)->connect(this, f, thrdid);
}

//结束状态
class xFinalState:public xstate{
    virtual void doAction(){
       xstateMachine* m = this->getmachine();
       if(m != nullptr)
            m->terminate();
            //
    }
};
#endif